package com.eight.cloud.admin.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.eight.cloud.admin.common.constant.CacheKeyConstant;
import com.eight.cloud.admin.entity.AppEntity;
import com.eight.cloud.admin.entity.SysTenantEntity;
import com.eight.cloud.admin.mapper.SysTenantMapper;
import com.eight.cloud.admin.model.dto.TenantDto;
import com.eight.cloud.admin.service.ISysTenantService;
import com.eight.cloud.core.utils.format.RandomStrUtil;
import com.eight.cloud.core.utils.quick.RSAUtils;
import com.eight.cloud.mybatisplus.entity.BaseEntity;
import com.eight.cloud.mybatisplus.service.BaseService;
import com.eight.cloud.openfeign.admin.vo.AppVo;
import com.eight.cloud.openfeign.admin.vo.TenantVo;
import com.eight.cloud.redisson.model.TypedKey;
import com.eight.cloud.redisson.utils.RedisUtils;
import com.fasterxml.jackson.core.type.TypeReference;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;

import static com.eight.cloud.core.global.constant.NumConstant.*;

/**
 * @ClassName: SysTenantServiceImpl
 * @Author: TXC
 * @Date: 2024-10-29 11:26
 **/
@Service
public class SysTenantServiceImpl extends BaseService<SysTenantMapper, SysTenantEntity> implements ISysTenantService {
    @Resource
    private RedisUtils redisUtils;

    @Override
    public SysTenantEntity add(SysTenantEntity tenant) {
        List<String> keyPair = RSAUtils.generateKeyPair(1024);
        tenant.setPublicKey(keyPair.get(ZERO));
        tenant.setPrivateKey(keyPair.get(ONE));
        baseMapper.insert(tenant);
        return tenant;
    }

    @Override
    public boolean edit(String uuid, TenantDto tenantDto) {
        SysTenantEntity tenant = baseMapper.selectOne(lambdaQueryWrapper().eq(BaseEntity::getUuid, uuid));
        tenant.setName(tenantDto.getName());
        return baseMapper.updateById(tenant) > 0;
    }

    @Override
    public TenantVo detail(String uuid) {
        String cacheKey = CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_TENANT_UUID, uuid);
        return redisUtils.cacheOrFetch(
                TypedKey.<TenantVo>builder().key(cacheKey).type(new TypeReference<>() {}).build(),
                () -> {
                    SysTenantEntity sysTenant = getByUuid(uuid);
                    if (ObjectUtil.isNull(sysTenant)) {
                        return null;
                    }
                    return convertToObject(sysTenant, TenantVo.class);
                }, WEEK_SECONDS);
    }

    @Override
    public TenantVo getTenantBySecretId(String secretId) {
        String cacheKey = CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_TENANT_SECRET, secretId);
        String tenantUuid = redisUtils.cacheOrFetch(
                TypedKey.<String>builder().key(cacheKey).type(new TypeReference<>() {}).build(),
                () -> {
                    SysTenantEntity sysTenant = baseMapper.selectOne(lambdaQueryWrapper().eq(SysTenantEntity::getSecretId, secretId));
                    if (ObjectUtil.isNull(sysTenant)) {
                        return null;
                    }
                    return sysTenant.getUuid();
                }, WEEK_SECONDS);
        return detail(tenantUuid);
    }

    @Override
    public String generateSecret(String uuid) {
        SysTenantEntity sysTenant = getByUuid(uuid);
        if (ObjectUtil.isNotNull(sysTenant) && ObjectUtil.isNotEmpty(sysTenant.getSecretId())) {
            return RSAUtils.encrypt(sysTenant.getSecretKey());
        }
        String secretKey = RandomStrUtil.getRandomStr(LONG_SIZE);
        String secretId = RandomStrUtil.getRandomStr(INT_SIZE);
        String encryptSecretKey = RSAUtils.encrypt(secretKey);
        redisUtils.delete(CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_TENANT_UUID, uuid));
        baseMapper.update(lambdaUpdateWrapper().set(SysTenantEntity::getSecretKey, encryptSecretKey)
                .set(SysTenantEntity::getSecretId, secretId)
                .eq(BaseEntity::getUuid, uuid));
        return encryptSecretKey;
    }

    @Override
    public String updateSecretKey(String uuid) {
        redisUtils.delete(CacheKeyConstant.generateKey(CacheKeyConstant.ADMIN_TENANT_UUID, uuid));
        String secretKey = RandomStrUtil.getRandomStr(LONG_SIZE);
        String encryptSecretKey = RSAUtils.encrypt(secretKey);
        baseMapper.update(lambdaUpdateWrapper().set(SysTenantEntity::getSecretKey, encryptSecretKey)
                .eq(BaseEntity::getUuid, uuid));
        return encryptSecretKey;
    }
}
